package 热题100.图论.腐烂的橘子_994_中等;

import java.util.Deque;
import java.util.LinkedList;

/*
在给定的 m x n 网格 grid 中，每个单元格可以有以下三个值之一：
值 0 代表空单元格；
值 1 代表新鲜橘子；
值 2 代表腐烂的橘子。
每分钟，腐烂的橘子 周围 4 个方向上相邻的新鲜橘子都会腐烂。
返回直到单元格中没有新鲜橘子为止所必须经过的最小分钟数。如果不可能，返回 -1 。

示例 1：
输入：grid = [[2,1,1],[1,1,0],[0,1,1]]
输出：4

示例 2：
输入：grid = [[2,1,1],[0,1,1],[1,0,1]]
输出：-1
解释：左下角的橘子（第 2 行， 第 0 列）永远不会腐烂，因为腐烂只会发生在 4 个方向上。

示例 3：
输入：grid = [[0,2]]
输出：0
解释：因为 0 分钟时已经没有新鲜橘子了，所以答案就是 0 。

提示：
m == grid.length
n == grid[i].length
1 <= m, n <= 10
grid[i][j] 仅为 0、1 或 2

思路：
    不能一个点开始遍历，是所有腐烂的橘子同时腐蚀四周，所以一开始就需要把所有腐烂的橘子进行统计。属于多路广搜
* */
public class Solution {
    public static void main(String[] args) {
        int[][] grid = {
                {2, 1, 1},
                {1, 1, 1},
                {0, 1, 2}
        };
        int[][] grid1 = {
                {0, 2}
        };
        System.out.println(orangesRotting(grid));
    }
    public static int orangesRotting(int[][] grid) {
        // 需要的时间  新鲜橘子的数量
        int ansTime = 0, freshCount = 0;
        // 上下左右四个
        int[][] f = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
        // 是否被遍历过
        boolean visit[][] = new boolean[grid.length][grid[0].length];
        // 存要腐蚀其他橘子的烂橘子
        Deque<int[]> deque = new LinkedList<>();

        for (int i = 0; i < grid.length; i ++){
            for (int j = 0; j < grid[0].length; j ++){
                if (!visit[i][j] && grid[i][j] == 2){
                   visit[i][j] = true;
                   deque.offer(new int[]{i, j});
                }else if(grid[i][j] == 1){
                    freshCount ++;
                }
            }
        }

        while (!deque.isEmpty() && freshCount > 0){
            int size = deque.size();
            // 判断是否腐蚀了，最后一轮橘子放进去了，但是其实已经没有好橘子可以腐蚀了
            // 走过一轮不判断的话，time会+1 但是不会这样！！，因为size没轮完，不会中途出来给time + 1
//            boolean flag = false;
            for (int j = 0; j < size; j ++){
                int[] t = deque.poll();
                for (int i = 0; i < 4; i ++){
                    int dx = f[i][0] + t[0], dy = f[i][1] + t[1];
                    if (dx >= 0 && dx < grid.length && dy >= 0 && dy < grid[0].length){
                        if (!visit[dx][dy] && grid[dx][dy] == 1){
                            visit[dx][dy] = true;
                            grid[dx][dy] = 2;
                            freshCount --;
//                            flag = true;
                            deque.offer(new int[]{dx, dy});
                        }
                    }
                }
            }
//            if (flag)
                ansTime ++;
        }
        if (freshCount != 0){
            return -1;
        }
        return ansTime;
    }
}
